import setting from "@/setting";
import { axiosRequest, requestInterceptorsOnAxios } from "./axios";
import { fetchRequset , requestInterceptorsOnFetch} from "./fetch";
import { socketCoonnect, socketSend , socketOnMessage , socketClose} from "./socket";
import sse from "./sse";
import type { AxiosResponse} from "axios";

type complete = {
    code : number,
    data : any
}

type RequestConfig = {
    /**请求之前拦截*/
    before?: (config : Record<string, any>) => void;
    /**请求错误拦截*/
    fail?: (error : any) => void;
    /**请求之后拦截*/
    after?: (response : Record<string, any>) => void;
}

type RequestOptions = {
    url : string,
    method? : string,
    data? : Record<string, any>,
    params? : Record<string, any>,
    headers? : Record<string, any>,
    loading? : boolean,
    loadingMsg? : string,
    uplodFile? : boolean,
    downFile? : boolean,
    success? : (res : Record<string, any>) => void,
    fail? : (error : any) => void,
    complete? : (res : complete) => void
}
/**
 * 请求方法
 * @param {object | String} options 请求参数配置 或者 请求地址
 * @param {string} options.url 请求地址
 * @param {string} [options.method] 请求方法
 * @param {object} [options.data] 请求参数
 * @param {object} [options.params] 请求参数 get
 * @param {object} [options.headers] 请求头
 * @param {Boolean} [options.loading] 是否显示loading
 * @param {string} [options.loadingMsg] loading提示信息
 * @param {Boolean} [options.downFile] 是否是文件下载
 * @param {number} [options.retryCount] 重试次数
 * @param {string} [options.responseType] 返回类型
 * @param {Function} [options.success] 成功回调
 * @param {Function} [options.fail] 失败回调
 * @param {Function} [options.complete] 完成回调
 * @param {string} [method] 请求方法 方便参数传递 调用
 * @param {object} [data] 请求参数 方便参数传递 调用
 * @param {Function} [callback] 回调函数 方便参数传递 调用
 * @returns {Promise} Promise对象
 * */

export const request = (options : RequestOptions, method ?: string, data ?: Record<string, any>, callback ?: (res : AxiosResponse<any, any> | {}) => Promise<any>):Promise<any> => {
    let option : RequestOptions = {
        url: "",
        method: "get",
        data: {},
        params: {},
        headers: {},
        loading: false,
        loadingMsg: "加载中...",
        uplodFile: false,
        downFile: false,
        success: () => { },
        fail: () => { },
        complete: () => { }
    }
    option.method = method || "get";
    option.data = data || {};
    option.success = callback || option.success;
    if (typeof options === "string") option.url = options;
    else option = Object.assign(option, options);
    if(option.method?.toUpperCase() === 'GET'){
        let params = '';
        let url = option.url;
        for(let key in options.params){
            params += `${key}=${options.params[key]}&`;
        }
        for(let key in options.data){
            params += `${key}=${options.data[key]}&`;
        }
        if(params){
            params = params.substring(0, params.length - 1);
            url += `?${params}&_t=${new Date().getTime()}`;
        }else{
            if(!url.includes('?')){
                url += `?_t=${new Date().getTime()}`;
            }else if(url.indexOf('?') === url.length - 1){
                url += `_t=${new Date().getTime()}`;
            }else{
                url += `&_t=${new Date().getTime()}`;
            }
        }
        option.params = {};
        option.data = {};
        option.url = url;
    }
    return new Promise((resolve, reject) => {
        if (!options) {
            let message = "请求数据为空";
            console.error(message);
            option.fail && option.fail(message);
            reject(message);
            return;
        }
        if (!option.url) {
            let message = "请求地址不能为空 本次请求已终止";
            console.error(message);
            option.fail && option.fail(message);
            reject(message);
            return;
        }

        if (setting.requestType == 'axios' || !window.fetch) {
            requestInterceptorsOnAxios();
            axiosRequest(option).then(res => {
                resolve(res);
            }).catch(err => {
                reject(err);
            })
            return;
        }
        fetchRequset(option).then(res =>{
            resolve(res);
        }).catch(err => {
            reject(err);
        })
    })
}

request.post = (options : RequestOptions | string, data ?: Record<string, any>, callback ?: (res : AxiosResponse<any, any> | {}) => Promise<any>) =>{
    let option : RequestOptions = {
        url: "",
        method: "post",
        data: {},
        params: {},
        headers: {},
        loading: false,
        loadingMsg: "加载中...",
        uplodFile: false,
        downFile: false,
        success: () => { },
        fail: () => { },
        complete: () => { }
    }
    if(typeof options === "string"){
        option.url = options;
    }else{
        option = Object.assign(option, options);
    }
    return request(option, "post", data, callback);
}

request.get = (options : RequestOptions | string, data ?: Record<string, any>, callback ?: (res : AxiosResponse<any, any> | {}) => Promise<any>) =>{
    let option : RequestOptions = {
        url: "",
        method: "get",
        data: {},
        params: {},
        headers: {},
        loading: false,
        loadingMsg: "加载中...",
        uplodFile: false,
        downFile: false,
        success: () => { },
        fail: () => { },
        complete: () => { }
    }
    if(typeof options === "string"){
        option.url = options;
    }else{
        option = Object.assign(option, options);
    }
    return request(option, "get", data, callback);
}

/**导出请求拦截*/ 
export const requestInterceptors = (options : RequestConfig) =>{
    if(setting.requestType == 'axios' || !window.fetch){
        requestInterceptorsOnAxios(options);
        return;
    }
    requestInterceptorsOnFetch(options);
}

/**
 * socket 链接
 * */ 
request.socket = {
    connect : socketCoonnect,
    send : socketSend,
    close : socketClose,
    onmessage : socketOnMessage,
}

/**sse链接*/
request.sse = sse;

export default request;